package org.jetlinks.pro.things.data;

import org.hswebframework.web.api.crud.entity.PagerResult;
import org.hswebframework.web.api.crud.entity.QueryParamEntity;
import org.jetlinks.core.message.ThingMessage;
import org.jetlinks.pro.timeseries.query.AggregationData;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Collection;

/**
 * 物实例数据存储策略
 *
 * @author zhouhao
 * @since 1.12
 */
public interface ThingDataStorageStrategy {

    /**
     * @return 策略ID
     */
    String getId();

    /**
     * @return 策略名称
     */
    String getName();

    /**
     * @return 策略描述
     */
    String getDescription();

    /**
     * 保存物消息,不同的消息保存逻辑不同。属性,事件将以时序方式保存, 其他只记录日志.
     *
     * @param message 消息
     * @return void
     */
    Mono<Void> save(ThingMessage message);

    /**
     * 根据条件查询属性,并返回属性列表
     *
     * @param thingId 物ID
     * @param param   查询参数
     * @return 属性列表
     */
    Flux<ThingPropertyDetail> queryProperty(@Nonnull String thingType,
                                            @Nonnull String thingId,
                                            @Nonnull String property,
                                            @Nonnull QueryParamEntity param);

    /**
     * 查询指定的属性列表,每一个属性都按查询条件进行过滤.
     *
     * @param thingType  物类型
     * @param thingId    物ID
     * @param properties 要查询的属性列表,为null或者为空集合时,查询全部的属性
     * @param param      查询条件
     * @return 属性列表
     */
    Flux<ThingPropertyDetail> queryProperties(@Nonnull String thingType,
                                              @Nonnull String thingId,
                                              @Nullable Collection<String> properties,
                                              @Nonnull QueryParamEntity param);

    /**
     * 根据条件分页查询属性,并返回属性列表
     *
     * @param thingId 物ID
     * @param param   查询参数
     * @return 属性分页查询结果
     */
    Mono<PagerResult<ThingPropertyDetail>> queryPropertyPage(@Nonnull String thingType,
                                                             @Nonnull String thingId,
                                                             @Nonnull String property,
                                                             @Nonnull QueryParamEntity param);

    /**
     * 聚合查询属性
     *
     * @param thingId    物ID
     * @param request    聚合请求
     * @param properties 属性聚合方式
     * @return 聚合查询结果
     */
    Flux<AggregationData> aggregationProperties(@Nonnull String thingType,
                                                @Nonnull String thingId,
                                                @Nonnull AggregationRequest request,
                                                @Nonnull PropertyAggregation... properties);

    /**
     * 聚合查询事件数据
     *
     * @param thingId    物ID
     * @param request    聚合请求
     * @param properties 属性聚合方式
     * @return 聚合查询结果
     */
    Flux<AggregationData> aggregationEvent(@Nonnull String thingType,
                                           @Nonnull String thingId,
                                           @Nonnull String event,
                                           @Nonnull AggregationRequest request,
                                           @Nonnull PropertyAggregation... properties);

    /**
     * 查询物的事件数据,支持分页,但是不进行count查询.
     *
     * @param thingType 物类型
     * @param thingId   物ID
     * @param event     物模型事件ID
     * @param param     查询条件
     * @return 事件数据
     */
    Flux<ThingEvent> queryEvent(@Nonnull String thingType,
                                @Nonnull String thingId,
                                @Nonnull String event,
                                @Nonnull QueryParamEntity param);

    /**
     * 分页查询物的事件数据
     *
     * @param thingType 物类型
     * @param thingId   物ID
     * @param event     物模型事件ID
     * @param param     查询条件
     * @return 事件数据
     */
    Mono<PagerResult<ThingEvent>> queryEventPage(@Nonnull String thingType,
                                                 @Nonnull String thingId,
                                                 @Nonnull String event,
                                                 @Nonnull QueryParamEntity param);

    /**
     * 查询物实例的消息日志,支持分页,但是不进行count查询.
     *
     * @param thingType 物类型
     * @param thingId   物实例ID
     * @param param     参数
     * @return 日志
     */
    Flux<ThingMessageLog> queryMessageLog(@Nonnull String thingType,
                                          @Nonnull String thingId,
                                          @Nonnull QueryParamEntity param);

    /**
     * 分页查询物实例的消息日志
     *
     * @param thingType 物类型
     * @param thingId   物实例ID
     * @param param     参数
     * @return 日志
     */
    Mono<PagerResult<ThingMessageLog>> queryMessageLogPage(@Nonnull String thingType,
                                                           @Nonnull String thingId,
                                                           @Nonnull QueryParamEntity param);
}
